#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>


#define NUM 1024

struct MyFILE_{
    int fd;
    char buffer[1024];
    int end; //当前缓冲区的结尾
};

typedef struct MyFILE_ MyFILE;


MyFILE *fopen_(const char *pathname, const char *mode)
{
    assert(pathname);
    assert(mode);

    MyFILE *fp = NULL;

    if(strcmp(mode,"r") == 0)
    {

    }
    else if(strcmp(mode,"r+") == 0)
    {

    }
    else if(strcmp(mode,"w") == 0)
    {
        int fd = open(pathname, O_WRONLY | O_TRUNC | O_CREAT,0666);
        if(fd >= 0)
        {
            fp =(MyFILE*)malloc(sizeof(MyFILE));
            memset(fp,0,sizeof(MyFILE));
            fp->fd = fd;
        }
    }
    else if(strcmp(mode,"w+") == 0)
    {

    }
    else if(strcmp(mode,"a") == 0)
    {

    }
    else if(strcmp(mode,"a+") == 0)
    {

    }
    else 
    {
        //什么都不做
    }
    return fp;

}

void fputs_(const char *message, MyFILE *fp)
{
    assert(message);
    assert(fp);

    strcpy(fp->buffer+fp->end,message);//abcde\0
    fp->end += strlen(message);

    //for debug
    printf("%s\n",fp->buffer);

    //暂时没有刷新,刷新策略是谁来执行的？用户通过执行C标准库中的代码逻辑，来完成刷新动作
    //这里效率提高，体现在哪里？因为C提供了缓冲区，那么我们就通过策略，减少了IO执行的次数(不是数据量)
    if(fp->fd == 0)
    {
        //标准输入
        
    }
    else if(fp->fd ==1)
    {
        //标准输出
        if(fp->buffer[fp->end-1] == '\n')
        {
            //fprintf(stderr,"fflush:%s",fp->buffer);
            write(fp->fd,fp->buffer,fp->end);
            fp->end = 0;
        }
    }
    else if(fp->fd == 2)
    {
        //标准错误
        
    }
    else 
    {
        //其他文件
        
    }
}

void fflush_(MyFILE *fp)
{
    assert(fp);
    if(fp->end != 0)
    {
        //暂且认为i刷新了--其实是把数据写到了内核
        write(fp->fd,fp->buffer,fp->end);
        syncfs(fp->fd); //将数据写入到磁盘
        fp->end = 0;
    }
}

void fclose_(MyFILE *fp)
{
    assert(fp);
    fflush_(fp);
    close(fp->fd);
    free(fp);
}



int main()
{
    //close(1);
    MyFILE *fp = fopen_("./log.txt","w");
    if(fp == NULL)
    {
        printf("open file error");
        return 1;
    }

    fputs_("one: hello world",fp);

    fork();

    fclose_(fp);
}























//int main(int argc,char *argv[])
//{
//    //C提供的
//    printf("hello printf\n");
//    fprintf(stdout,"hello fprintf\n");
//    const char *s = "hello fputs\n";
//    fputs(s,stdout);
//
//    //OS提供的
//    const char *ss = "hellow write\n";
//    write(1,ss,strlen(ss));
//
//    //fork之前强制刷新
//    fflush(stdout);
//
//    //在最后调用的fork，上面的函数已经被执行完了(并不代表数据已经刷新了)
//    fork();//创建子进程







    //if(argc != 2)
    //{
    //    return 2;
    //}

    //int fd = open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
    ////int fd = open("log.txt",O_WRONLY|O_CREAT|O_APPEND);
    //if(fd < 0)
    //{
    //    perror("open");
    //    return 1;
    //}
    //dup2(fd,1);
    //fprintf(stdout, "%s\n",argv[1]); // stdout -> 1 -> 显示器

    //close(fd);

    //close(1);
    //int fd = open("log.txt",O_WRONLY|O_TRUNC|O_CREAT);
    //if(fd < 0)
    //{
    //    perror("open");
    //    return 1;
    //}
    //fprintf(stdout,"you can see me, success\n");
    //return 0;

   // printf("fd:%d\n",fd);

   // char buffer[64];
   // fgets(buffer,sizeof buffer,stdin);
   // printf("%s\n",buffer);






//    close(1);
//    //这里的fd的分配规则是：最小的，没有被占用的文件描述符 
//    //0,1,2->close(1)->fd->1
//    int fd = open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);
//    if(fd < 0)
//    {
//        perror("open");
//        return 1;
//    }
//
//    //都应该是往显示器(标准输出)打印的
//    //但是下面的都写入(显示)到了log.txt文件中
//    //是为什么呢？输出重定向 
//
//    printf("fd:%d\n",fd);//stdout->FILE{fileno=1}->log.txt
//    printf("fd:%d\n",fd);
//    printf("fd:%d\n",fd);
//    printf("fd:%d\n",fd);
//    printf("fd:%d\n",fd);
//    printf("fd:%d\n",fd);
//    fprintf(stdout,"hello fprintf\n");
//    const char *s = "hello fwrite";
//    fwrite(s,strlen(s),1,stdout);
//
//    fflush(stdout);
//    //stdout->_fileno == 1;
//
//    //close(fd); //
//    return 0;
//}
